import { useMemo, useRef } from 'react';
import { isFunction } from '../utils';

// 定义一个类型别名来表示任意函数类型（在 JavaScript 中，这部分是注释掉的，因为不需要类型定义）
// type noop = (this: any, ...args: any[]) => any;

// 在 JavaScript 中，我们不定义这样的类型工具，因为它们仅用于 TypeScript 的类型检查
// type PickFunction<T extends noop> = (
//   this: ThisParameterType<T>,
//   ...args: Parameters<T>
// ) => ReturnType<T>;

function useMemoizedFn(fn) {
  if (process.env.NODE_ENV === 'development') {
    if (!isFunction(fn)) {
      console.log(
        'useMemoizedFn',
        `expected parameter is a function, got ${typeof fn}`
      );
    }
  }

  const fnRef = useRef(fn);

  // 使用 useMemo 来记忆函数引用，尽管在这种情况下直接赋值给 fnRef.current 也是可行的，
  // 但使用 useMemo 可以确保在函数 fn 变化时更新引用，同时避免在每次渲染时都创建一个新的函数实例（尽管在这个特定例子中可能不是必需的）。
  // 注意：这里的 [fn] 依赖项数组确保了当 fn 变化时，useMemo 会返回一个新的函数实例。
  fnRef.current = useMemo(() => fn, [fn]);

  // 创建一个记忆化的函数实例
  const memoizedFn = useRef();
  if (!memoizedFn.current) {
    memoizedFn.current = function (...args) {
      return fnRef.current.apply(this, args);
    };
  }

  // 返回记忆化的函数实例
  return memoizedFn.current;
}

export default useMemoizedFn;
